package com.fei.myback.config;

import com.fei.myback.common.*;
import com.fei.myback.filter.JwtFilter;
import com.fei.myback.service.User.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;

import java.util.UUID;

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    private static final String DEFAULT_REMEMBER_ME_KEY = UUID.randomUUID().toString();
    ;
    @Autowired
    NullLogin NullLogin;//未登陆时返回 JSON 格式的数据给前端（否则为 html）

    @Autowired
    SuccessLogin SuccessLogin; //登录成功返回的 JSON 格式数据给前端（否则为 html）

    @Autowired
    FailLogin FailLogin; //登录失败返回的 JSON 格式数据给前端（否则为 html）

    @Autowired
    SuccessLoginOut SuccessLoginOut;//注销成功返回的 JSON 格式数据给前端（否则为 登录时的 html）

    @Autowired
    NullRole NullRole;//无权访问返回的 JSON 格式数据给前端（否则为 403 html 页面）

    @Autowired
    UserServiceImpl UserServiceImpl; // 自定义user

    @Autowired
    JwtFilter JwtFilter; // JWT 拦截器

    @Autowired
    RoleContro roleContro;//权限控制器

    @Autowired
    RoleMap roleMap;//权限集合

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 加入自定义的安全认证
//        auth.authenticationProvider(provider);
        auth.userDetailsService(UserServiceImpl).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    public void configure(WebSecurity webSecurity) {
        webSecurity.ignoring().antMatchers(
                "/css/**",
                "/js/**",
                "/index.html",
                "/login",
                "/logout",
                // swagger-boostrap-ui
                "/doc.html",
                "/webjars/**",
                "/v2/api-docs/**",
                "/swagger-resources/**"

        )
                .antMatchers(HttpMethod.OPTIONS)
                .requestMatchers(CorsUtils::isPreFlightRequest);   //对preflight放行;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 去掉 CSRF
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 使用 JWT，关闭session
                .and()

                //配置Spring Security,设置不拦截OPTIONS请求
                /*     .requestMatcher(CorsUtils::isPreFlightRequest)
                     .authorizeRequests()
                     .antMatchers(HttpMethod.OPTIONS)
                     .permitAll()
                     //特别注意，因为在上面configure（）做了对url的处理，所以不需要再在这里做
                     .and()*/
                //使用自定义的未登录返回信息
                .httpBasic().authenticationEntryPoint(NullLogin)
                .and()

                //定义哪些URL需要被保护、哪些不需要被保护

                .authorizeRequests()
                //.antMatchers( "/resources/**", "/doc.html" , "/swagger-ui/**").permitAll()

                .anyRequest()//除以上任何请求,登录后才可以访问
                .authenticated()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setAccessDecisionManager(roleContro);
                        o.setSecurityMetadataSource(roleMap);
                        return o;
                    }
                });
        //.access("@rbacauthorityservice.hasPermission(request,authentication)") // RBAC 动态 url 认证

/*                .and()
                .formLogin()  //开启登录, 定义当需要用户登录时候，转到的登录页面
//                .loginPage("/test/login.html")
//                .loginProcessingUrl("/login")
                .successHandler(SuccessLogin) // 登录成功
                .failureHandler(FailLogin) // 登录失败
                .permitAll()*/

                /*.and()
                .logout()//默认注销行为为logout
                .logoutUrl("/logout")
                .logoutSuccessHandler(SuccessLoginOut)
                .permitAll();*/

        // 记住我
/*        http.rememberMe().rememberMeParameter("remember-me")
                .userDetailsService(UserServiceImpl).tokenValiditySeconds(1000);*/
        // http.cors(Customizer.withDefaults());
        http.exceptionHandling().accessDeniedHandler(NullRole); // 无权访问 使用自定的返回信息
        http.addFilterBefore(JwtFilter, UsernamePasswordAuthenticationFilter.class); // JWT Filter
    }

}
